home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Ham Radio 2000 #2
/
Ham Radio 2000 - Volume 2.iso
/
HAMV2
/
TCP_IP
/
TNOS230S
/
MAILBOX2.C
< prev
next >
Wrap
C/C++ Source or Header
|
1997-08-18
|
67KB
|
2,713 lines
/* NOTE: because of size, the previous 'mailbox.c' has been
* split in 3 parts:
* pbbscmd.c, containing the 'pbbs' subcommands, and
* mailbox.c, containing some user mailbox commands, and
* mailbox2.c, containing the remaining user commands.
* 921125 - WG7J
*/
/* There are only two functions in this mailbox code that depend on the
* underlying protocol, namely mbx_getname() and dochat(). All the other
* functions can hopefully be used without modification on other stream
* oriented protocols than AX.25 or NET/ROM.
*
* SM0RGV 890506, most work done previously by W9NK
*
*** Changed 900114 by KA9Q to use newline mapping features in stream socket
* interface code; everything here uses C eol convention (\n)
*
* Numerous new commands and other changes by SM0RGV, 900120
*
* Gateway function now support outgoing connects with the user's call
* with inverted ssid. Users can connect to system alias as well...
* See also several mods in socket.c,ax25.c and others
* 11/15/91, WG7J/PA3DIS
*
* Userlogging, RM,VM and KM commands, and R:-line interpretation
* added 920307 and later, Johan. K. Reinalda, WG7J/PA3DIS
*
* Inactivity timeout-disconnect added 920325 and later - WG7J
*
* Removed pbbs overhead from calling Convers directly from ax25 - KO4KS
* Several other additions - KO4KS
*/
#include "global.h"
#include "ctype.h"
#include "commands.h"
#ifdef MSDOS
#include <dir.h>
#include <dos.h>
#else
#include <time.h>
#endif
#ifdef UNIX
#include <sys/stat.h>
#endif
#include "timer.h"
#include "proc.h"
#include "socket.h"
#include "usock.h"
#include "session.h"
#include "smtp.h"
#include "ftpserv.h"
#include "bm.h"
#include "pktdrvr.h"
#include "help.h"
#if !defined(_lint)
static char rcsid[] OPTIONAL = "$Id: mailbox2.c,v 1.32 1997/08/19 01:19:22 root Exp root $";
#endif
#ifdef DELEGATE
#include "delegate.h"
extern int Mbdelegate;
#endif
#ifdef UNIX
extern int ftpsecuritycheck (char *filename, int perms, int mode);
extern long CREATEgid, CREATEuid;
extern short CREATEmask;
extern int CREATEsecure;
#ifndef R_OK
#define R_OK 4
#endif
#ifndef W_OK
#define W_OK 2
#endif
#endif
extern int AMPRonly;
extern char Compiled[];
extern int MAttended;
extern char *MAttendedAt;
extern char Mbpasswd[];
extern int BbsUsers;
extern char Only[];
extern char CurUsers[];
extern char Howtoend[];
extern char MsgAborted[];
extern char *findhome (char *);
extern void suspendTipMail (struct mbx *m);
extern void tutorserv (const char *call, struct mbx *m, int mode, int color, int ip);
#ifdef MBFWD
extern void forwardingSummary (void);
#endif
extern int dombusers (int argc, char *argv[], void *p);
extern struct list *expandalias (struct list **head, const char *user, const char *orig);
extern char *Mbhaddress;
extern int doencode (int argc, char *argv[], void *p);
extern struct cmds Cmds[];
extern struct cmds Mbcmds[];
#ifdef MAILBOX
void bbsbump (char *user, int zap);
int bid_check (register char *string);
#ifdef WPAGES
static void wpageUpdate (FILE * fp, char *string, char *entry, char *oldtime, int bbs, int updateit, char which);
#endif
int groupcommand (char *action, char *group, char *user, int local, FILE ** out, FILE * in);
int isgroup (char *group);
static void informGroup (char *action, char *group, char *user, char *buf, FILE * old, FILE * new, FILE * in);
#ifdef USERLOG
static int quickstat (register struct mbx *m, char *area);
#endif
static int dombgetall (struct mbx *m);
static void expertstat (struct mbx *m);
#ifdef FILECMDS
static int uuencode (FILE *infile, int s, char *infilename);
static int uudecode (FILE *infile, FILE *outfile);
#endif
int dombencode (int argc, char *argv[], void *p);
int dodownload (int argc, char *argv[], void *p);
int dombfdesc (int argc, char *argv[], void *p);
int dobump (int argc, char *argv[], void *p);
int msgidcheck (char *string);
int dombwpages (int argc, char *argv[], void *p);
int dombnews (int argc, char *argv[], void *p);
int dombtutor (int argc, char *argv[], void *p);
int dombgroup (int argc, char *argv[], void *p);
int dombquote (int argc, char *argv[], void *p);
int dombset (int argc, char *argv[], void *p);
int dombrmail (int argc, char *argv[], void *p);
int dombroute (int argc, char *argv[], void *p);
int dombexpand (int argc, char *argv[], void *p);
int dombexpert (int argc, char *argv[], void *p);
int dombslip (int argc, char *argv[], void *p);
int douser (int argc, char *argv[], void *p);
int doreply (int argc, char *argv[], void *p);
int dombget (int argc, char *argv[], void *p);
int dombmovemail (int argc, char *argv[], void *p);
int dombhelp (int argc, char *argv[], void *p);
int dombconvers (int argc, char *argv[], void *p);
int dombfinger (int argc, char *argv[], void *p);
int dosysop (int argc, char *argv[], void *p);
int dostars (int argc, char *argv[], void *p);
int dochat (int argc, char *argv[], void *p);
int dombjheard (int argc, char *argv[], void *p);
int dombiproute (int argc, char *argv[], void *p);
#ifdef LZW
void togglelzw (int soc, int mode);
#endif
#ifdef WPAGES
void wpageAdd (char *entry, int bbs, int updateit, char which);
char *wpageCheck (char *string, int bbs, int updateit, char which);
void add_WPUpdate (char *call, char *home, char *name, char which);
#endif
char *wpage_exp (char *to, int hier, int exphome);
int dozap (int argc, char *argv[], void *p);
int dowhat (int argc, char *argv[], void *p);
extern int dosend (int argc, char *argv[], void *p);
extern char *permtest (char *path, long privs, const char *name, int mode, char *root, int thedir);
extern char *cmd_line (int argc, char *argv[], char stype);
extern char *nntp_name_expansion (char *name);
extern void updateCtl (const char *who, struct let *info);
#if defined(FOQ_CMDS) || defined(TTYCALL) || defined(ALLSERV)
const char SysopBusy[] = "The system is unattended. Try again later.\n";
#endif
#ifdef CATALOG
#include "catalog.h"
#define CAT mailbox2_catalog
#define Alsomenu __STR(0)
#define Alsomenu2 __STR(1)
#define index_dat __STR(2)
#define sorry __STR(3)
#define wr_syntax __STR(4)
#define wa_syntax __STR(5)
#define noread __STR(6)
#define dirdenied __STR(7)
#define zapfailed __STR(8)
#define logzap __STR(9)
#define zapdenied __STR(10)
#define attemptsysop __STR(11)
#define sysopdenied __STR(12)
#define validationcomplete __STR(13)
#define sysopwarning __STR(14)
#define logsysop __STR(15)
#define loglinkdenied __STR(16)
#define loglink __STR(17)
#define linkhello __STR(18)
#define ampronly_str __STR(19)
#define telnetdenied __STR(20)
#define logtelnet __STR(21)
#define incomingcall __STR(22)
#define finger_usage __STR(23)
#define confnotenabled __STR(24)
#define convdenied __STR(25)
#define logconf __STR(26)
#define logtutor __STR(27)
#define nohelp __STR(28)
#define onlyfirst __STR(29)
#define cannotlock __STR(30)
#define message __STR(31)
#define moreafter __STR(32)
#define areaadded __STR(33)
#define nameadded __STR(34)
#define newscanlogin __STR(35)
#define usaANSI __STR(36)
#define permissionlevel __STR(37)
#define fwddelegation __STR(38)
#define usecompressed __STR(39)
#define expertprompts __STR(40)
#define usersettings __STR(41)
#define useSET __STR(42)
#define getheader __STR(43)
#define gettrailer __STR(44)
#define noconfig __STR(45)
#define delegationdisabled __STR(46)
#define expandsto __STR(47)
#define noaddress __STR(48)
#define addressroutes __STR(49)
#define unreadmessages __STR(50)
#define newmessages __STR(51)
#define nounreadmessages __STR(52)
#if 0
#define systemtime __STR(53)
#endif
#define inform_str __STR(54)
#define groupindex __STR(55)
#define newsdisabled __STR(56)
#define lognews __STR(57)
#define wp_syntax __STR(58)
#define notinwp __STR(59)
#if 0
#define wplists __STR(60)
#endif
#define wplists2 __STR(61)
#define wp_sysopsyntax __STR(62)
#define updating __STR(63)
#define filedesc __STR(64)
#define downloaddenied __STR(65)
#define xmodemtip __STR(66)
#define uploaddenied __STR(67)
#define cannotopen __STR(68)
#define cannotcreate __STR(69)
#define logupload __STR(70)
#define Sysopmenu __STR(71)
#else
static const char Alsomenu[] =
"\nFor further help, type 'help cmdname', where 'cmdname' is one of the above."
"\nFor a brief listing of all commands, type '?'\n\n";
static const char Alsomenu2[] =
"Others: AF, AL, AN, AS, DU, KM, KS, KU, L$, L>, L<, LA, LB, LL, LM, LS, LT,\n"
" ML, MS, RH, RM, SB, SC, SF, SP, SR, ST, VM, XA, XC, XM, XN, XS\n";
static const char Sysopmenu[] = "Sysops: IF, MA, MC, MF, MH, MK, MM, MP, MR, MT, MW, MX, WA, WR, @\n";
static const char index_dat[] = "index.dat";
static const char sorry[] = "Sorry, command is only available to the SYSOP!\n";
static const char wr_syntax[] = "Syntax: WR user \"message\"\n";
static const char wa_syntax[] = "Syntax: WA \"message\"\n";
static const char noread[] = "Can't read directory: \"%s\": %s\n";
static const char dirdenied[] = "%s: directory denied: %s\n";
static const char zapfailed[] = "Zap failed: %s\n";
static const char logzap[] = "PBBS Zap: %s";
static const char zapdenied[] = "%s: zap denied: %s\n";
static const char attemptsysop[] = "PBBS: %s attempting SYSOP";
static const char sysopdenied[] = "%s: SYSOP denied!\n";
static const char validationcomplete[] = "Validation %somplete!\n";
static const char sysopwarning[] = "\nType 'exit' to return\n\nBe VERY careful!!\n";
static const char logsysop[] = "PBBS sysop: %s";
static const char loglinkdenied[] = "PBBS LINKED: %s permission denied";
static const char loglink[] = "PBBS LINKED: %s changed to %s";
static const char linkhello[] = "Oh, hello %s.\n";
static const char ampronly_str[] = "Sorry, but only Amateur Radio IP stations can be reached from here!\n";
static const char telnetdenied[] = "%s: Telnet denied: %s\n";
static const char logtelnet[] = "PBBS TELNET: %s to %s:%d";
static const char incomingcall[] = "*** Incoming call from %s@%s ***\n";
static const char finger_usage[] = "Usage: F user@host or F @host or F user.\n";
static const char confnotenabled[] = "Conference server not enabled\n";
static const char convdenied[] = "%s: converse denied\n";
static const char logconf[] = "PBBS CONFERENCE: %s";
static const char logtutor[] = "PBBS TUTORIAL: %s";
static const char nohelp[] = "No help available.\n";
static const char onlyfirst[] = "Only first %d arguments used\n";
static const char cannotlock[] = "Can't lock '%s', please try later\n";
static const char message[] = "Message %d %s...\n";
static const char moreafter[] = "-more- after %d lines\n";
static const char areaadded[] = "Area added to prompt";
static const char nameadded[] = "Name added to prompt";
static const char newscanlogin[] = "New message scan at login";
static const char usaANSI[] = "Use ANSI color graphics";
static const char permissionlevel[] = "Permission level: %ld (0x%08lx)\n";
static const char fwddelegation[] = "Forward delegation";
static const char usecompressed[] = "Use Compressed streams";
static const char expertprompts[] = "Expert user prompts";
static const char usersettings[] = "*** User profile settings: %s ***\n\n";
static const char useSET[] = "\nUse the SET command to change these options. For help, type HELP SET.\n";
static const char getheader[] = "---------------- Current %s Information ----------------\n";
static const char gettrailer[] = "---------------- %s %s Information ----------------\n";
static const char noconfig[] = "This command not configured for this interface\n";
static const char delegationdisabled[] = "Forwarding delegation disabled by SYSOP\n";
static const char expandsto[] = "Address '%s' expands to: ";
static const char noaddress[] = "No address specified.\n";
static const char addressroutes[] = "Address '%s' routes to:";
static const char unreadmessages[] = "%s ha%s unread messages, in the following message areas:\n";
static const char newmessages[] = "As a new user, you will find messages in the following message areas:\n";
static const char nounreadmessages[] = "No unread messages in the public areas! %s %s up-to-date!\n";
#if 0
static const char systemtime[] = "The system time at '%s' is now: %s\n";
#endif
static const char inform_str[] = "%s: SUBSCRIBED %s";
static const char groupindex[] = "Index of mailing lists/groups\n\n";
static const char newsdisabled[] = "News Center not enabled\n";
static const char lognews[] = "PBBS NEWS: %s";
static const char wp_syntax[] = "Syntax: WP user%s\n";
static const char notinwp[] = "Sorry, user not in whitepages! If local user, try \"ML user\"...\n";
#if 0
static const char wplists[] = "White Pages lists this person as '%s@%s'\n";
#endif
static const char wplists2[] = "White Pages lists this person as '%s'\n";
static const char wp_sysopsyntax[] = "Syntax: WP user @bbsname\n";
static const char updating[] = "Updating database....\n";
static const char filedesc[] = "Enter description lines, each line 37 characters maximum.\n'/EX' when complete:\n";
static const char downloaddenied[] = "%s: download denied: %s\n";
static const char xmodemtip[] = "Xmodem on TIP connects only\n";
static const char uploaddenied[] = "%s: upload denied: %s\n";
static const char cannotopen[] = "Can't open \"%s\": %s\n";
static const char cannotcreate[] = "Can't create \"%s\": %s\n";
static const char logupload[] = "PBBS upload: %s";
#endif
short SecureTelnet = 1;
#ifdef MSDOS
#define WPAGEENTRYSIZE 30
#define WPAGEBBSENTRYSIZE 49
#else
#define WPAGEENTRYSIZE 29
#define WPAGEBBSENTRYSIZE 48
#endif
int
dowhat (int argc, char *argv[], void *p)
{
struct mbx *m;
#ifdef FILECMDS
FILE *fp, *in = NULLFILE;
char *file;
char *cp, *nm, *ptr;
char buf[50], buf2[80];
int yep;
#endif
#ifdef DOS_GETFILEATTR
unsigned attr;
#endif
m = (struct mbx *) p;
#ifdef WPAGES
if (m->stype == 'P')
return (dombwpages (argc, argv, p));
#endif
if (((m->stype == 'R') || (m->stype == 'A')) && !(m->privs & SYSOP_CMD)) {
tputs (sorry);
return 0;
}
if (m->stype == 'R') {
if (argc < 3)
tputs (wr_syntax);
else
(void) dowrite (0, argv, 0);
return 0;
}
if (m->stype == 'A') {
if (argc < 2)
tputs (wa_syntax);
else
(void) dowriteall (0, argv, 0);
return 0;
}
#ifdef FILECMDS
if ((file = permtest (m->path, m->privs, (argc > 1) ? argv[1] : ".", RETR_CMD, NULLCHAR, (argc < 2))) != NULLCHAR) {
m->state = MBX_WHAT;
/* check for index.dat file in that directory */
cp = strdup (file);
#ifdef DOS_GETFILEATTR
(void) _dos_getfileattr (cp, &attr);
if (!(attr & FA_DIREC)) {
ptr = strrchr (cp, '/');
if (ptr)
*ptr = 0;
}
#endif
nm = pathname (cp, index_dat);
free (cp);
in = fopen (nm, READ_TEXT);
free (nm);
if (in != NULLFILE) {
tputc ('\n');
while (fgets (buf2, 80, in) != NULLCHAR) {
if (*buf2 == ' ' || *buf2 == '\t' || *buf2 == '\n')
tputs (buf2);
else
break;
}
}
if ((fp = dir (file, (in == NULLFILE) ? 1 : 2)) == NULLFILE)
tprintf (noread, file, SYS_ERRLIST(errno));
else {
#ifdef MBXTDISC
stop_timer (&m->tdisc);
#endif
if (in == NULLFILE)
(void) sendfile (fp, m->user, ASCII_TYPE, 0);
else {
while (fgets (buf, 50, fp) != NULLCHAR) {
yep = 0;
if (*buf == ' ')
continue;
rewind (in);
while (fgets (buf2, 80, in) != NULLCHAR) {
if (!strnicmp (buf, buf2, 12)) {
yep = 1;
rip (buf2);
break;
}
}
if (yep)
rip (buf);
tputs (buf);
if (yep) {
ptr = &buf2[13];
ptr = skipwhite (ptr);
tprintf ("%-37.37s\n", ptr);
while (fgets (buf2, 80, in) != NULLCHAR) {
if (*buf2 != ' ' && *buf2 != '\t')
break;
rip (buf2);
ptr = skipwhite (buf2);
tprintf ("%39s| %-37.37s\n", "", ptr);
}
}
}
(void) fclose (in);
}
(void) fclose (fp);
}
free (file);
} else {
tputs (Noperm);
mail_error (dirdenied, m->name, cmd_line (argc, argv, m->stype));
}
#endif
return 0;
}
#ifdef FILECMDS
int
dozap (int argc, char *argv[], void *p)
{
struct mbx *m;
char *file;
m = (struct mbx *) p;
if ((file = permtest (m->path, m->privs, argv[1], DELE_CMD, NULLCHAR, 0)) != NULLCHAR) {
if (unlink (file))
tprintf (zapfailed, SYS_ERRLIST(errno));
else
log (m->user, logzap, file);
free (file);
} else {
tputs (Noperm);
mail_error (zapdenied, m->name, cmd_line (argc, argv, m->stype));
}
return 0;
}
#endif
extern void dumproute (struct route *rp, char *p);
extern const char RouteHeader[];
/* Show non-private routes only */
int
dombiproute (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
{
register int i, bits;
register struct route *rp;
char buf[85];
tputs (RouteHeader);
for (bits = 31; bits >= 0; bits--) {
for (i = 0; i < HASHMOD; i++) {
for (rp = Routes[bits][i]; rp != NULLROUTE; rp = rp->next) {
if (!(rp->flags & RTPRIVATE)) {
dumproute (rp, buf);
if (tprintf ("%s\n", &buf[4]) == EOF)
return 0;
}
}
}
}
if (R_default.iface != NULLIF && !(R_default.flags & RTPRIVATE)) {
dumproute (&R_default, buf);
if (tprintf ("%s\n", &buf[4]) == EOF)
return 0;
}
return 0;
}
#ifdef AX25
int
dombjheard (int argc, char *argv[], void *p)
{
struct iface *ifp;
struct mbx *m = (struct mbx *) p;
if (argc > 1) {
if (((ifp = if_lookup (argv[1])) == NULLIF) || (ifp->type != CL_AX25) ||
((ifp->flags & HIDE_PORT) && !(m->privs & MBX_SYSOP))) {
tprintf (Badinterface, argv[1]);
return 0;
}
(void) axheard (ifp);
return 0;
}
for (ifp = Ifaces; ifp != NULLIF; ifp = ifp->next) {
if ((ifp->flags & LOG_AXHEARD) && (!(ifp->flags & HIDE_PORT) || m->privs & MBX_SYSOP))
if (axheard (ifp) == EOF)
break;
}
return 0;
}
#endif
#if defined(FOQ_CMDS) || defined(TTYCALL)
int
dochat (int argc OPTIONAL, char *argv[] OPTIONAL, void *p)
{
char buf[8], *newargv[3], doitat[50], buf2[2];
struct mbx *m;
m = (struct mbx *) p;
if (MAttended) {
m->state = MBX_CHAT;
strcpy (buf2, "C");
newargv[0] = buf2;
newargv[1] = Hostname;
if (MAttendedAt != NULLCHAR) {
strncpy (doitat, MAttendedAt, 50);
newargv[1] = doitat;
rip (newargv[1]);
}
sprintf (buf, "%d", IPPORT_TTYLINK);
newargv[2] = buf;
SecureTelnet = 0;
m->stype = '+';
(void) dombtelnet (3, newargv, p);
} else
tputs (SysopBusy);
/* It returns only after a disconnect or refusal */
return 0;
}
#endif
/*Password protection added - 920118, WG7J */
int
dosysop (int argc OPTIONAL, char *argv[] OPTIONAL, void *p)
{
struct mbx *m;
int c;
int len, pwdc[5], i, valid = 0;
char *cp;
m = (struct mbx *) p;
log (m->user, attemptsysop, m->name);
/*If you want anyone with the password to go sysop-mode
*comment out the next 4 line ! -WG7J
*/
if (!(m->privs & SYSOP_CMD)) {
tputs (Noperm);
mail_error (sysopdenied, m->name);
return 0;
}
/*only if set,
*check for the password before letting users proceed
*/
m->state = MBX_SYSOPTRY;
if ((len = (int) strlen (Mbpasswd)) != 0) {
for (i = 0; i < 5; i++)
tprintf ("%d ", (pwdc[i] = RANDOM (len)) + 1); /*print the random chars*/
tputc ('\n');
for ( ; ; ) {
c = mbxrecvline (m);
if (c == EOF || c == -2)
return 0;
if (*m->line == '\0')
break;
if (*m->line == '?') {
tprintf (validationcomplete, valid ? "C" : "Inc");
continue;
}
cp = m->line;
for (i = 0; i < 5; i++)
if (tolower (*cp++) != tolower (Mbpasswd[pwdc[i]]))
break;
if (i == 5)
valid = 1;
}
if (!valid)
return 0;
}
log (m->user, "PBBS: %s is now SYSOP", m->name);
m->state = MBX_SYSOP;
tputs (sysopwarning);
for ( ; ; ) {
netPrompt ();
usflush (Curproc->output);
if (mbxrecvline (m) < 0)
break;
log (m->user, logsysop, m->line);
#ifdef MBXTDISC
stop_timer (&m->tdisc);
#endif
if (*m->line == '\0')
continue;
cp = _variable_expansion (strdup (m->line));
strncpy (m->line, cp, MBXLINE);
free (cp);
/* Check for special commands. Execute these mailbox cmds. KF5MG. */
#if defined AX25 || defined NETROM
if (strncmp (m->line, "connect", strcspn (m->line, " ")) == 0)
valid = cmdparse (Mbcmds, m->line, (void *) m);
else
#endif
#ifdef FOQ_CMDS
if (strncmp (m->line, "finger", strcspn (m->line, " ")) == 0)
valid = cmdparse (Mbcmds, m->line, (void *) m);
else
#endif
#ifdef GATECMDS
if (strncmp (m->line, "ping", strcspn (m->line, " ")) == 0)
valid = cmdparse (Mbcmds, m->line, (void *) m);
else if (strncmp (m->line, "telnet", strcspn (m->line, " ")) == 0)
valid = cmdparse (Mbcmds, m->line, (void *) m);
else
#endif
valid = cmdparse (Cmds, m->line, NULL);
#ifdef MBXTDISC
start_timer (&m->tdisc);
#endif
if (valid == -2)
break;
}
/* remove potential remote traces - WG7J */
removetrace ();
return 0;
}
/* Handle the "*** Done" command when reverse forwarding ends or the
* "*** LINKED to" command.
*/
int
dostars (int argc, char *argv[], void *p)
{
struct mbx *m;
int anony = 1;
int founddigit = 0;
int oldprivs;
char *cp;
m = (struct mbx *) p;
/* Allow 'linked to' from anyone, but reset SYSOP priviledges
* when the sysop-password is not set !
* Also try to set the new call !
* Inspired by Kurt, wb5bbw
* Check for the strange TEXNET linked message !
* 920220 - WG7J
*/
if ((argc >= 4) && !strcmp (argv[1], "linked") && !strcmp (argv[2], "to")) {
if (m->privs & NO_LINKEDTO) {
puts (Noperm);
#ifdef GWTRACE
log (m->user, loglinkdenied, m->name);
#endif
return 0;
}
#ifdef GWTRACE
log (m->user, loglink, m->name, argv[3]);
#endif
strncpy (m->name, argv[3], MBXLINE);
oldprivs = m->privs; /*Save this !*/
/* Try to find the privileges of this user from the userfile */
if ((m->privs = userlogin (m->name, NULLCHAR, &m->path, MBXLINE,
&anony)) == -1)
if ((m->privs = userlogin ("bbs", NULLCHAR, &m->path,
MBXLINE, &anony)) == -1)
if ((m->privs = userlogin ("anonymous", NULLCHAR,
&m->path, MBXLINE, &anony)) == -1) {
m->privs = 0;
free (m->path);
m->path = NULLCHAR;
}
if (m->privs & EXCLUDED_CMD)
return domboxbye (0, NULLCHARP, p);
#ifdef AX25
/* Set the call */
for (cp = m->name; *cp != '\0'; cp++)
if (isdigit ((int) *cp))
break;
if (*cp != '\0')
founddigit = 1;
if ((setcall (m->call, m->name) == -1) || (!founddigit)) {
m->privs &= ~AX25_CMD;
m->privs &= ~NETROM_CMD;
}
#else
m->privs &= ~AX25_CMD;
m->privs &= ~NETROM_CMD;
#endif
/*Kill ssid in name, if any*/
if ((cp = strchr (m->name, '-')) != NULLCHAR)
*cp = '\0';
/*Check if sysop password is set,
*if not, disallow sysop privs no matter what !
*/
if (*Mbpasswd == '\0')
m->privs &= ~SYSOP_CMD;
/*Check to see if any of NO_READ,NO_SEND or NO_3PARTY were set,
*if so, dis-allow those no matter what
*(so that users cannot get priviledges by issuing a ***linked)
* 920220 - WG7J
*/
if (oldprivs & NO_SENDCMD)
m->privs |= NO_SENDCMD;
if (oldprivs & NO_READCMD)
m->privs |= NO_READCMD;
if (oldprivs & NO_3PARTY)
m->privs |= NO_3PARTY;
tprintf (linkhello, m->name);
#ifdef MAILCMDS
changearea (m, m->name, (int) 1);
#endif
return 0;
}
if (argc > 1 && (m->sid & MBX_SID)) /* "*** Done" or similar */
return -2;
return -1;
}
#if defined(GATECMDS) || defined(FOQ_CMDS)
int
dombtelnet (int argc, char *argv[], void *p)
{
struct mbx *m;
int s, len, i;
int nonampr = 0;
char dsocket[MAXSOCKSIZE];
struct sockaddr_in fsocket;
short wasSecureTelnet;
wasSecureTelnet = SecureTelnet;
SecureTelnet = 1;
m = (struct mbx *) p;
fsocket.sin_family = AF_INET;
if (argc < 3)
fsocket.sin_port = IPPORT_TELNET;
else {
/* if m->stype == '+' we were called internally */
if (m->stype != '+' && (m->privs & NO_NON23)) {
tputs ("\nSorry, but you do not have permission to specify a non-standard telnet port!\n");
return 0;
}
fsocket.sin_port = (int16) atoip (argv[2]);
}
if ((fsocket.sin_addr.s_addr = resolve (argv[1])) == 0) {
tprintf (Badhost, argv[1]);
/* Free m->startmsg if set ! - WG7J */
if (m->startmsg != NULLCHAR) {
free (m->startmsg);
m->startmsg = NULLCHAR;
}
return 0;
}
nonampr = (((fsocket.sin_addr.s_addr & 0xff000000LU) >> 24) != 44);
if (AMPRonly && (m->privs & WAS_ANONY) && nonampr) {
tputs (ampronly_str);
/* Free m->startmsg if set ! - WG7J */
if (m->startmsg != NULLCHAR) {
free (m->startmsg);
m->startmsg = NULLCHAR;
}
return 0;
}
/* Only local telnets are are allowed to the unprivileged user */
/* The above is a security hole ! DO NOT allow this anymore ! - WG7J */
/* If the first letter of the command is 'C', then it was
* the CALL,QUERY,OPERATOR or CONFERENCE command !
* Allow these, no matter what.
* This way, you can give access to the Internet callserver,
* but disable all other telnets - WG7J
*/
if (wasSecureTelnet && *argv[0] != 'C') {
if ((nonampr && !(m->privs & TELNET_CMD)) || (!nonampr && !(m->privs & AMPR_CMD))) {
tputs (Noperm);
mail_error (telnetdenied, m->name, cmd_line (argc, argv, m->stype));
#ifdef TUTOR
strcpy (m->line, "denied telnet");
mbscripthook (m, "denied.sys");
#endif
/* Free m->starmsg if set ! - WG7J */
/* Shouldn't happen here, but just in case */
if (m->startmsg != NULLCHAR) {
free (m->startmsg);
m->startmsg = NULLCHAR;
}
return 0;
}
}
if ((s = socket (AF_INET, SOCK_STREAM, 0)) == -1) {
tputs (Nosock);
/* Free m->starmsg if set ! - WG7J */
if (m->startmsg != NULLCHAR) {
free (m->startmsg);
m->startmsg = NULLCHAR;
}
return 0;
}
#ifdef GWTRACE
log (m->user, logtelnet, m->name, argv[1], fsocket.sin_port);
#endif
if (fsocket.sin_port == IPPORT_TTYLINK) {
m->startmsg = mallocw (80);
len = MAXSOCKSIZE;
i = getpeername (m->user, dsocket, &len);
sprintf (m->startmsg, incomingcall, m->name, i != -1 ? psocket (dsocket) : Hostname);
}
m->state = MBX_GATEWAY;
return gw_connect (m, s, (struct sockaddr *) &fsocket, SOCKSIZE);
}
#endif
#ifdef FOQ_CMDS
int
dombfinger (int argc, char *argv[], void *p)
{
struct mbx *m;
char *host, *user = NULLCHAR, buf[8], *newargv[3], buf2[2];
if (argc > 2) {
tputs (finger_usage);
return -1;
}
host = Hostname;
if (argc == 2) {
if ((host = strchr (argv[1], '@')) != NULLCHAR) {
*host = '\0';
host++;
} else
host = Hostname;
user = argv[1];
}
m = (struct mbx *) p;
m->startmsg = mallocw (80);
if (user != NULLCHAR)
sprintf (m->startmsg, "%s\n", user);
else
strcpy (m->startmsg, "\n");
buf2[0] = 't';
buf2[1] = 0;
newargv[0] = buf2;
newargv[1] = host;
sprintf (buf, "%d", IPPORT_FINGER);
newargv[2] = buf;
SecureTelnet = 0;
m->stype = '+';
return dombtelnet (3, newargv, p);
}
#endif
extern int Mbconverse;
#ifdef CONVERS
int
dombconvers (int argc, char *argv[], void *p)
{
struct mbx *m;
int channel = -1;
struct session *sp;
m = (struct mbx *) p;
if (!Mbconverse) {
tputs (confnotenabled);
return 0;
}
if (m->privs & NO_CONVERS) {
tputs (Noperm);
mail_error (convdenied, m->name);
#ifdef TUTOR
strcpy (m->line, "denied converse");
mbscripthook (m, "denied.sys");
#endif
return 0;
}
if (argc != 1)
channel = atoi (argv[1]);
#ifdef GWTRACE
log (m->user, logconf, m->name);
#endif
m->state = MBX_CONVERS;
usflush (Curproc->output);
if (Current->type == 1)
tprintf ("%c%c", IAC, CLEARSCREEN); /* sets Current->split */
sp = Current;
kwait (NULL);
mbox_converse (m->user, m->name, channel, m);
if (sp->split) {
usflush (Curproc->output);
tprintf ("%c%c", IAC, CLEARSPLIT); /* clears Current->split */
usflush (Curproc->output);
sp->split = 0;
}
return 0;
}
#endif
#ifdef TUTOR
extern int Sinfo;
#endif
int
dombhelp (int argc, char *argv[], void *p)
{
char buf[255];
FILE *fp;
struct mbx *m;
m = (struct mbx *) p;
#ifdef MBFWD
if ((m->stype == 'F') && (m->privs & SYSOP_CMD)) {
forwardingSummary ();
return 0;
}
#endif
if (m->stype == 'H')
return (doipheard (argc, argv, p));
if (m->stype == 'P')
return (dombiproute (argc, argv, p));
buf[0] = '\0';
/* check for "?" and "help" here */
if (*argv[0] == '?' || *argv[0] == 'h') {
bbscolorcls (m);
bbscolorchange (m, "07");
(void) dombxhelp (argc, argv, p);
if (*argv[0] == '?' && argc == 1) {
bbscolorchange (m, "0B");
tputs (Alsomenu);
tputs (Alsomenu2);
if (m->privs & SYSOP_CMD)
tputs (Sysopmenu);
bbscolorchange (m, "09");
sprintf (buf, "%s/help.hlp", Helpdir);
goto also;
}
return 0;
}
#ifdef TUTOR
if (Sinfo != -1) {
log (m->user, logtutor, m->name);
m->state = MBX_TUTOR;
tutorserv (m->name, m, 1, m->usecolor, 0);
} else {
#endif
tprintf (Nosversion, Version, Compiled);
tprintf ((BbsUsers == 1) ? Only : CurUsers, BbsUsers);
sprintf (buf, "%s/sysinfo.hlp", Helpdir);
also:
if ((fp = fopen (buf, READ_TEXT)) != NULLFILE) {
(void) sendfile (fp, Curproc->output, ASCII_TYPE, 0);
(void) fclose (fp);
} else {
if (argc > 1 && *argv[0] == 'h')
tputs (nohelp);
}
#ifdef TUTOR
}
#endif
return 0;
}
#ifdef MAILCMDS
extern char Badmsg[];
extern char Nomail[];
/* Move messages from current area to another */
int
dombmovemail (int argc, char *argv[], void *p)
{
int num, i;
int movebuf[NARG];
char *to;
struct mbx *m;
char buf[MBXLINE];
FILE *Mfile; /* file to move to */
struct let *cmsg;
long size;
int thisone, wrcntr, sawempty;
struct let lt;
char *tmpbuf;
int msg, maxmsg;
m = (struct mbx *) p;
if (argc == 1) {
char const *which;
which = (m->stype == 'M') ? "move" : (m->stype == 'W') ? "write" : "copy";
tprintf ("Syntax: M%c area - %s current message\n M%c n1 [n2...] %s - %s message n1 (n2...)\n",
m->stype, which, m->stype, (m->stype == 'W') ? "filename" : "area", which);
return 0;
}
if (m->mfile == NULLFILE) {
tputs (Nomail);
return 0;
}
if (argc == 2) {
/* NO message #, use current message */
num = 1;
to = argv[1];
movebuf[0] = m->current;
} else {
/* Scan all message # to move */
num = 0;
for (i = 1; i < argc - 1; i++) {
tmpbuf = strchr (argv[i], '-');
msg = atoi (argv[i]);
if (tmpbuf == NULLCHAR)
maxmsg = msg;
else
maxmsg = atoi (++tmpbuf);
if (!msg || maxmsg < msg) {
tprintf (Badmsg, argv[i]);
continue;
}
for (; msg <= maxmsg; msg++) {
if (msg > m->nmsgs)
tprintf (Badmsg, msg);
else
movebuf[num++] = msg;
if (num == NARG)
break;
}
if (num == NARG)
tprintf (onlyfirst, NARG);
}
to = argv[argc - 1];
}
if (m->stype != 'W')
(void) nntp_name_expansion (to);
/* Now try to lock the destination file, if not a write */
if (m->stype != 'W')
if (mlock (Mailspool, to) == -1) {
tprintf (cannotlock, to);
return 0;
}
/* open the destination file for appending */
if (m->stype == 'W') {
char *pp;
pp = permtest (m->path, m->privs, to, STOR_CMD, NULLCHAR, 0);
if (!pp)
return 0;
strncpy (buf, pp, MBXLINE);
free (pp);
} else
sprintf (buf, "%s/%s.txt", Mailspool, to);
if ((Mfile = fopen (buf, "a")) == NULLFILE) {
tprintf ("Can't open '%s'\n", buf);
if (m->stype != 'W')
rmlock (Mailspool, to);
return 0;
}
/* Okay, let's do the work */
for (i = 0; i < num; i++) {
thisone = movebuf[i]; /*lint !e644 */
cmsg = &m->mbox[thisone];
/* find start of this message */
fseek (m->mfile, cmsg->start, 0);
size = cmsg->size;
(void) fflush (Mfile);
lt.size = cmsg->size;
lt.bid = cmsg->bid;
lt.status = 0;
lt.start = (long) filelength (fileno (Mfile));
wrcntr = 0;
sawempty = 0;
/* now read this message */
while (size > 0 && fgets (buf, MBXLINE, m->mfile) != NULLCHAR) {
kwait (NULL);
if (!sawempty && strlen (buf) == 1) /* "\n" - dunno about DOS */
sawempty = 1;
if (m->stype == 'W' && !sawempty) /* trim headers on "MW" */
trimrightCR (buf);
if (m->stype != 'W' || wrcntr > 2)
fputs (buf, Mfile);
wrcntr += 1;
size -= (long) strlen (buf);
}
#ifdef USERLOG
if (m->stype == 'M' || m->stype == 'C') {
updateCtl (to, <);
}
#endif
/* delete this message, if moving */
if (m->stype == 'M') {
cmsg->status |= BM_DELETE;
cmsg->status &= ~BM_ONHOLD;
statusCtl (m->area, "ctl", cmsg, thisone, 0);
if (!issysarea (m->area))
m->change |= CHG_DELETE;
}
tprintf (message, thisone, (m->stype == 'M') ? "moved" : (m->stype == 'W') ? "written" : "copied");
}
(void) fclose (Mfile);
if (m->stype != 'W') {
#ifdef ALERTMONITOR
alertarea (to);
#endif
rmlock (Mailspool, to);
}
return 0;
}
#endif
static void
expertstat (struct mbx *m)
{
char const *p;
int32 flag;
switch (m->stype) {
case 'M':
tprintf (moreafter, m->morerows);
return;
case 'A':
p = areaadded;
flag = m->sid & MBX_AREA;
break;
case 'N':
p = nameadded;
flag = m->sid & MBX_NRID;
break;
case 'S':
p = newscanlogin;
flag = m->sid & MBX_STATS;
break;
case 'G':
p = usaANSI;
flag = m->sid & MBX_GFX;
break;
case 'P':
tprintf (permissionlevel, m->privs, m->privs);
return;
#ifdef DELEGATE
case 'D':
display_delegation (m->name);
p = fwddelegation;
flag = m->sid & MBX_DELEGATE;
break;
#endif
#ifdef LZW
case 'C':
p = usecompressed;
flag = m->sid & MBX_TNOS;
break;
#endif
case 'X':
case ' ':
p = expertprompts;
flag = m->sid & MBX_EXPERT;
break;
default:
return;
}
tprintf ("%s: o%s\n", p, (flag) ? "n" : "ff");
return;
}
static int
dombgetall (struct mbx *m)
{
char *args[2];
char buf[4];
tprintf (usersettings, m->name);
m->stype = 'M'; expertstat (m);
m->stype = 'A'; expertstat (m);
m->stype = 'N'; expertstat (m);
m->stype = 'S'; expertstat (m);
m->stype = 'G'; expertstat (m);
m->stype = 'C'; expertstat (m);
#ifdef LZW
m->stype = 'X'; expertstat (m);
#endif
m->stype = 'P'; expertstat (m);
strcpy (buf, "F");
args[1] = buf;
(void) dombget (2, args, m);
strcpy (buf, "Si");
args[1] = buf;
(void) dombget (2, args, m);
#ifdef DELEGATE
strcpy (buf, "D");
args[1] = buf;
(void) dombget (2, args, m);
#endif
tputs (useSET);
return 0;
}
int
dombget (int argc, char *argv[], void *p)
{
struct mbx *m;
int cnt;
if (argc == 1)
return (dombgetall (p));
m = (struct mbx *) p;
m->stype = (char) toupper (*argv[1]);
if (m->stype != 'F' && strnicmp (argv[1], "Si", 2)) {
expertstat (m);
return 0;
}
sprintf (m->line, "%s/%s%s", (m->stype == 'F') ? FingerDir : Signature, m->name, (m->stype == 'S') ? ".sig" : "");
tprintf (getheader, (m->stype == 'F') ? "Finger" : "Signature");
cnt = DisplayFile (m->line, m->user);
tprintf (gettrailer, (cnt) ? "End of" : "No", (m->stype == 'F') ? "Finger" : "Signature");
return 0;
}
#ifdef MAILCMDS
int
doreply (int argc, char *argv[], void *p)
{
register struct mbx *m;
m = (struct mbx *) p;
m->stype = 'R';
return (dosend (argc, argv, p));
}
#endif
int
douser (int argc, char *argv[], void *p)
{
register struct mbx *m;
m = (struct mbx *) p;
m->stype = 'L';
return (dombusers (argc, argv, p));
}
#ifdef TIPMAIL
int
dombslip (int argc OPTIONAL, char *argv[] OPTIONAL, void *p)
{
register struct mbx *m;
m = (struct mbx *) p;
if (m->type != TIP) {
tputs (noconfig);
return (0);
}
if (m->privs & NO_SLIP) {
tputs (Noperm);
return 0;
}
suspendTipMail (m);
return -2;
}
#endif
int
dombexpert (int argc, char *argv[], void *p)
{
struct mbx *m;
#ifdef LZW
struct usock *up;
#endif
m = (struct mbx *) p;
switch (m->stype) {
case 'M':
if (argc == 1) {
tprintf (moreafter, m->morerows);
return 0;
} else {
m->morerows = atoi (argv[1]);
}
break;
case 'A':
m->sid ^= MBX_AREA;
break;
case 'G':
m->sid ^= MBX_GFX;
m->usecolor ^= 1;
break;
case 'N':
m->sid ^= MBX_NRID;
break;
case 'S':
m->sid ^= MBX_STATS;
break;
#ifdef DELEGATE
case 'D':
if (Mbdelegate) {
m->sid ^= MBX_DELEGATE;
if (m->sid & MBX_DELEGATE)
setup_delegate (m);
else
clear_delegate (m);
} else {
tputs (delegationdisabled);
m->sid &= ~MBX_DELEGATE;
return 0;
}
break;
#endif
#ifdef LZW
case 'C':
m->sid ^= MBX_TNOS;
up = itop (m->user);
if ((m->sid & MBX_TNOS) || (up->zout != NULLLZW))
togglelzw (m->user, m->sid & MBX_TNOS);
break;
#endif
case ' ':
case 'X':
m->sid ^= MBX_EXPERT;
break;
default:
return 0;
}
m->update = 1;
expertstat (m);
return 0;
}
int
dombexpand (int argc OPTIONAL, char *argv[], void *p OPTIONAL)
{
struct list *ap, *list;
char *arg, *orig, *newaddr, buf[LINELEN];
int loopindex;
tprintf (expandsto, argv[1]);
arg = argv[1];
list = NULLLIST;
orig = strdup (arg);
/* rewrite address if possible */
if ((newaddr = rewrite_address (arg, 0)) != NULLCHAR)
if (strcmp (newaddr, arg) == 0) {
free (newaddr);
newaddr = NULLCHAR;
} else {
strncpy (buf, newaddr, LINELEN);
arg = buf;
}
list = NULLLIST;
(void) expandalias (&list, arg, orig);
free (orig);
if (list == NULLLIST) {
tprintf ("nothing");
return 0;
}
if (strcmp (list->val, arg) == 0 && list->next == NULLLIST)
if (newaddr == NULLCHAR) {
tprintf ("'%s'\n", arg);
del_list (list);
return 0;
}
ap = list;
loopindex = 0;
while (ap->next != NULLLIST) {
if (!(loopindex++ % 2))
tputc ('\n');
tputs (" ");
tprintf ("%-32.32s", ap->val);
ap = ap->next;
}
tprintf ("%s %s\n", (loopindex % 2) ? "" : "\n", ap->val);
del_list (list);
free (newaddr);
return 0;
}
#ifdef MBFWD
int
dombroute (int argc OPTIONAL, char *argv[], void *p OPTIONAL)
{
char *arg, *newaddr;
#if 0
char buf[LINELEN];
#endif
int k, loopindex;
arg = argv[1];
if (!arg) {
tputs (noaddress);
return 1;
}
tprintf (addressroutes, argv[1]);
/* rewrite address if possible */
if ((newaddr = rewrite_address (arg, 0)) == NULLCHAR)
newaddr = strdup (argv[1]);
for (loopindex = 0, k = 0; k < Numfwds; k++)
if (AREAlookup (newaddr, k)) {
if (!(loopindex++ % 3))
tputs ("\n ");
tprintf ("%-25.25s", MyFwds[k].name);
}
tputc ('\n');
free (newaddr);
return 0;
}
#endif
#ifdef RMAIL
int
dombrmail (int argc, char *argv[], void *p)
{
int orgchange;
struct mbx *m;
char *cp;
m = (struct mbx *) p;
if (!(m->sid & MBX_SID)) { /* not available to BBSs */
orgchange = m->change;
m->change = -1;
m->stype = 'C';
cp = mallocw (strlen (argv[1]) + 8);
sprintf (cp, "rmail@%s", argv[1]);
argv[1] = cp;
(void) dosend (argc, argv, p);
m->change = orgchange;
free (cp);
}
return 0;
}
#endif
#ifdef LZW
void
togglelzw (int soc, int mode)
{
struct usock *up;
if ((up = itop (soc)) == NULLUSOCK)
return;
tprintf ("%c%c%c%c", IAC, COMPRESSED, (Lzwmode) ? 'f' : 'c', Lzwbits);
usflush (soc);
if (mode) {
lzwinit (soc, Lzwbits, Lzwmode);
up->zin->maxbits = -1;
} else
lzwfree (up);
usflush (soc);
if (socklen (soc, 0)) /* discard any remaining input */
(void) recv_mbuf (soc, NULL, 0, NULLCHAR, 0);
}
#endif
int
dombset (int argc, char *argv[], void *p)
{
struct mbx *m;
m = (struct mbx *) p;
m->stype = (char) toupper (*argv[1]);
if (!strnicmp (argv[1], "Si", 2))
m->stype = '$';
if (m->stype == 'F' || m->stype == '$')
return (dombupload (argc, argv, p));
else
return (dombexpert (argc - 1, &argv[1], p));
}
#ifdef USERLOG
/* Routine for quickly checking an area for messages that are new to this user.
This routine reads the area.ctl files, which contains a bid for each message. */
static int
quickstat (register struct mbx *m, char *area)
{
long last, newlast, lastone;
char oldarea[64], buf[256];
FILE *fp;
register int retval = 0;
last = m->lastread;
newlast = m->newlastread;
m->lastread = 0;
strncpy (oldarea, m->area, 64);
strncpy (m->area, area, 64);
(void) strlwr (m->area);
(void) nntp_name_expansion (m->area);
/* only read last read message-id if current area is a public area
* and not 'help' or area starts with 'sys'
* read in all cases if a SYSOP
*/
if ((stricmp (area, "help") && isarea (area)) || !strnicmp (m->area, "sys", 3) || (m->privs & SYSOP_CMD))
getlastread (m);
kwait (NULL);
lastone = m->lastread;
m->lastread = last;
m->newlastread = newlast;
sprintf (buf, "%s/control/%s.ctl", Mailspool, m->area);
if ((fp = fopen (buf, READ_BINARY)) != NULLFILE) {
struct let lt;
long size;
size = (long) (filelength (fileno (fp)) - sizeof (struct let));
fseek (fp, size, SEEK_SET);
(void) fread (<, sizeof (struct let), 1, fp);
(void) fclose (fp);
if (lt.bid > lastone)
retval = 1;
}
strncpy (m->area, oldarea, 64);
kwait (NULL);
return retval;
}
void
quickscan (struct mbx *m, int olduser, int usename)
{
char const *cp;
char *cp2;
FILE *fp;
char buf[MBXLINE];
char out[MBXLINE];
char const *initmsg;
int found = 0, length = 3;
cp = Arealist;
if ((m->privs & SYSOP_CMD) && (!access (AreaSlist, 0)))
cp = AreaSlist;
if ((fp = fopen (cp, READ_TEXT)) == NULLFILE)
return;
if (olduser)
initmsg = unreadmessages;
else
initmsg = newmessages;
strcpy (out, " ");
while (fgets (buf, MBXLINE, fp) != NULLCHAR) {
kwait (NULL);
if (isalnum (buf[0])) { /* skip comments */
if ((cp2 = strpbrk (buf, " \t\n\r")) != NULLCHAR)
*cp2 = '\0';
/* statarea (m, buf, &total, &new, &hold, 0);
if (new) { */
if (quickstat (m, buf)) {
if (!found) {
tprintf (initmsg, (usename) ? m->name : "You", (usename) ? "s" : "ve");
found++;
}
length += (int) (strlen (buf) + 2);
strcat (out, buf);
strcat (out, " ");
}
if (length > 70) {
tputs (out);
tputc ('\n');
out[3] = 0;
length = 3;
}
}
}
if (length != 3) {
tputs (out);
tputc ('\n');
}
(void) fclose (fp);
if (!found)
tprintf (nounreadmessages, (usename) ? m->name : "You", (usename) ? "is" : "are");
}
#endif
#if defined(FOQ_CMDS)
int
dombquote (int argc, char *argv[], void *p)
{
char *host, buf[8], *newargv[3], buf2[2];
struct mbx *m;
m = (struct mbx *)p;
host = Hostname;
if (argc == 2)
host = argv[1];
buf2[0] = 't';
buf2[1] = 0;
newargv[0] = buf2;
newargv[1] = host;
sprintf (buf, "%d", IPPORT_QUOTE);
newargv[2] = buf;
SecureTelnet = 0;
m->stype = '+';
return dombtelnet (3, newargv, p);
}
#endif
static void
informGroup (
char *action OPTIONAL,
char *group,
char *user,
char *buf,
FILE *old,
FILE *new,
FILE *in
) {
char subj[68], *cp;
sprintf (subj, inform_str, user, group);
while (fgets (buf, 50, old) != NULLCHAR) {
fputs (buf, new);
if (*buf != ' ')
break;
if (buf[strlen (buf) - 2] == 'I') {
if ((cp = strchr (&buf[1], ' ')) != NULLCHAR)
*cp = 0;
if (in)
rewind (in);
(void) rdaemon (in, NULLCHAR, NULLCHAR, &buf[1], subj, 'P', 0);
}
}
}
int
isgroup (char *group)
{
FILE *old;
register len, retval = 0;
char buf[80];
if (!group)
return 0;
len = (int) strlen (group);
if ((old = fopen (Group, UPDATE_TEXT)) == NULLFILE)
return 0;
while (fgets (buf, 80, old) != NULLCHAR) {
if (!strnicmp (buf, group, (unsigned) len) && buf[len] == ':') {
retval = 1;
break;
}
}
(void) fclose (old);
return retval;
}
int
groupcommand (
char *action,
char *group,
char *user,
int local,
FILE **out,
FILE *in
) {
FILE *new, *old;
char *newname, *cp;
int found = 0, retval = 0;
char which, buf[80], subj[68];
unsigned len;
if ((old = fopen (Group, UPDATE_TEXT)) == NULLFILE)
if ((old = fopen (Group, CREATE_TEXT)) == NULLFILE)
return 0;
newname = (char *) mallocw (strlen (Group) + 5);
sprintf (newname, "%s.new", Group);
if ((new = fopen (newname, CREATE_TEXT)) == NULLFILE) {
(void) fclose (old);
free (newname);
return 0;
}
*action = (char) tolower (*action);
if (*action == 'l') { /* list groups */
if (!local)
fprintf (new, groupindex);
while (fgets (buf, 50, old) != NULLCHAR) {
if (*buf != ' ' && (cp = strchr (buf, ':')) != 0) {
*cp++ = '\n';
*cp = 0;
if (!local)
fputs (buf, new);
else
tputs (buf);
}
}
if (!local) {
rewind (new);
strcpy (subj, "GROUP LISTING");
(void) rdaemon (new, NULLCHAR, NULLCHAR, user, subj, 'P', 0);
}
retval = 1;
goto confuzed;
}
if (group == NULLCHAR)
goto confuzed;
len = strlen (group);
if (*action != 'a') {
while (fgets (buf, 50, old) != NULLCHAR) {
if (!strnicmp (buf, group, len) && buf[len] == ':') {
found = 1;
break;
}
fputs (buf, new);
}
if (!found)
goto confuzed;
if (*action != 'd')
fputs (buf, new);
}
switch (tolower (*action)) {
case 'a':
fprintf (new, "%s:\n\n", group);
break;
case 'i':
fprintf (new, " %s I\n", user);
break;
case 's':
fprintf (new, " %s S\n", user);
rip (buf);
if (local)
(void) DisplayFile (&buf[len + 2], Curproc->output);
else
*out = fopen (&buf[len + 2], READ_TEXT);
informGroup (action, group, user, buf, old, new, in);
break;
case 'u':
len = strlen (user);
which = (char) ((strlen (action) < 3) ? 's' : tolower (action[2]));
while (fgets (buf, 50, old) != NULLCHAR) {
if (*buf != ' ') {
fputs (buf, new);
break;
}
if (strnicmp (&buf[1], user, (unsigned) len) ||
tolower (buf[strlen (buf) - 2]) != which)
fputs (buf, new);
else
break;
}
break;
case 'd':
while (fgets (buf, 50, old) != NULLCHAR)
if (*buf != ' ') {
if (*buf != '\n')
fputs (buf, new);
break;
}
break;
default:
goto confuzed;
}
while (fgets (buf, 50, old) != NULLCHAR)
fputs (buf, new);
(void) fclose (new);
(void) fclose (old);
unlink (Group);
(void) rename (newname, Group);
free (newname);
return 1;
confuzed:
(void) fclose (new);
(void) fclose (old);
unlink (newname);
free (newname);
return retval;
}
int
dombgroup (int argc, char *argv[], void *p)
{
struct mbx *m;
char cmd;
int retval = 1;
m = (struct mbx *) p;
cmd = (char) tolower (*argv[1]);
if (cmd != 's' && cmd != 'u' && cmd != 'l' && (m->privs == -1 || !(m->privs & SYSOP_CMD)))
retval = 0;
if (!retval || (cmd != 'l' && argc < 3) || !groupcommand (argv[1], (argc > 2) ? argv[2] : NULLCHAR, (argc > 3 && m->privs & SYSOP_CMD) ? argv[3] : m->name, 1, (FILE **) 0, (FILE *) 0))
tputs ("Denied!\n");
else
tputs ("Approved!\n");
return 0;
}
#ifdef TUTOR
extern int Stutor, Snews;
int
dombtutor (int argc OPTIONAL, char *argv[] OPTIONAL, void *p)
{
struct mbx *m;
m = (struct mbx *) p;
if (Stutor == -1) {
tputs ("Tutorial server not enabled\n");
return 0;
}
log (m->user, logtutor, m->name);
m->state = MBX_TUTOR;
tutorserv (m->name, m, 0, m->usecolor, 0);
return 0;
}
int
dombnews (int argc OPTIONAL, char *argv[] OPTIONAL, void *p)
{
struct mbx *m;
m = (struct mbx *) p;
if (Snews == -1) {
tputs (newsdisabled);
return 0;
}
log (m->user, lognews, m->name);
m->state = MBX_TUTOR;
tutorserv (m->name, m, 2, m->usecolor, 0);
return 0;
}
#endif
char *
wpage_exp (
char *to,
int hier OPTIONAL,
int exphome OPTIONAL /* append and expand home bbs name ? */
) {
#if (defined(ASKHOME) || defined(WPAGES))
char *cp = (char *) -1;
char *cp2;
char origbbs[40];
#ifdef WPAGES
char buf[12];
#endif
if (strchr (to, '%'))
return (to);
#ifdef ASKHOME
/* This section adds the HOME BBS to any messages to known users that do
not have "@bbs" portions of the TO address, except when user is a BBS */
cp2 = strchr (to, '@');
cp = NULLCHAR;
if ((cp2 == NULLCHAR) && (cp = findhome (to)) != (char *) NULL) {
if (cp != (char *) -1) { /* home no here */
sprintf (origbbs, "%s@%s", to, cp);
free (to);
free (cp);
to = strdup (origbbs);
}
}
#endif /* ASKHOME */
#ifdef WPAGES
/* This section looks up the destination bbs in the White Pages file, if user not a BBS
If found, the complete address is substituted */
#ifdef ASKHOME
if (cp != (char *) -1) { /* if home not here */
#else
if (cp == (char *) -1) {
#endif
cp2 = strchr (to, '@');
if (cp2 == NULLCHAR) { /* no dest BBS given */
if ((cp2 = wpageCheck (to, 0, 0, 'X')) != NULLCHAR) { /* found the bbs */
free (to);
(void) strlwr (cp2);
to = cp2;
}
cp2 = strchr (to, '@');
}
if (hier && cp2 != NULLCHAR) { /* we have a dest bbs, get correct, full haddress */
cp = cp2++;
if ((cp2 = wpageCheck (cp2, 1, 0, 'X')) != NULLCHAR) {
*cp = '\0';
sprintf (origbbs, "%s@%s", to, cp2);
free (to);
free (cp2);
(void) strlwr (origbbs);
to = strdup (origbbs);
}
}
} else if (exphome) {
(void) pax25 (buf, Mycall);
if ((cp = strpbrk (buf, DIGI_IDS)) != NULLCHAR)
*cp = '\0'; /* remove SSID */
sprintf (origbbs, "%s@%s%s%s", to, buf,
(Mbhaddress != NULLCHAR) ? "." : "",
(Mbhaddress != NULLCHAR) ? Mbhaddress : "");
free (to);
to = strdup (origbbs);
}
#endif /* WPAGES */
#endif /* ASKHOME || WPAGES */
kwait (NULL);
return (to);
}
#ifdef WPAGES
extern int MbWpages;
int
dombwpages (int argc, char *argv[], void *p)
{
struct mbx *m;
char buf[80], *cp, *cp2, origchar = 0;
m = (struct mbx *) p;
if (argc < 2) {
tprintf (wp_syntax, m->privs & SYSOP_CMD ? " [@bbsname]" : "");
return 0;
}
if (!(m->privs & SYSOP_CMD) && argc > 2) {
tputs (sorry);
return 0;
}
if (argc == 2) { /* lookup */
cp = wpageCheck (argv[1], 0, 0, 'X');
if (!cp)
tputs (notinwp);
else {
cp2 = wpage_exp (strdup (argv[1]), 1, 1);
(void) strupr (cp2);
tprintf (wplists2, cp2);
free (cp2);
free (cp);
}
} else { /* else, setting it */
if (argv[2][0] != '@')
tputs (wp_sysopsyntax);
else {
if ((cp = strchr (argv[2], '.')) != NULLCHAR) {
sprintf (buf, &argv[2][1]);
(void) strupr (buf);
wpageAdd (buf, 1, 1, 'U');
origchar = *cp;
*cp = 0;
}
sprintf (buf, "%s%s", argv[1], argv[2]);
(void) strlwr (buf);
wpageAdd (buf, 0, 1, 'U');
if (cp && origchar)
*cp = origchar;
tputs (updating);
tflush ();
kwait (NULL);
RenewWPages ();
}
}
return 0;
}
static void
wpageUpdate (
FILE *fp,
char *string,
char *entry,
char *oldtime OPTIONAL,
int bbs,
int updateit,
char which
) {
time_t now;
char buf[LINELEN], *cp;
char compare[40];
int thesize, changed = 0;
int thelen;
long offset;
/* parameters string and oldtime are not being used, yet */
thesize = (bbs) ? 32 : 13;
(void) time (&now);
/* make a comparison string from 'string' */
strncpy (buf, string, (unsigned) thesize);
buf[thesize] = 0;
if ((cp = strchr (buf, ' ')) != NULLCHAR)
*cp = 0;
/* make a comparison string from 'entry' */
strncpy (compare, entry, (unsigned) thesize);
compare[thesize] = 0;
if ((cp = strchr (compare, ' ')) != NULLCHAR)
*cp = 0;
if (!bbs && (cp = strchr (buf, '.')) != NULLCHAR)
*cp = 0;
/* has this entry changed ? */
if (stricmp (compare, buf))
changed = 1;
/* if we are updating it, take the NEW entry */
if (updateit && which != 'G')
entry = buf;
/* write the old or new entry, with the new timestamp and close file */
fprintf (fp, "%-*s %-14ld\n", thesize, entry, now);
(void) fclose (fp);
kwait (NULL);
/* If we were updating the entry and the entry DID change..... */
if (changed && which != 'T') {
if (updateit) {
/* now we update the temporary wpages */
if (!bbs) { /* no temp for wpagebbs */
char buf2[LINELEN];
if ((cp = strchr (buf, '@')) != NULLCHAR)
thelen = (int) (cp - buf);
else
thelen = (int) strlen (buf);
if ((fp = fopentmp (WhitePages, READ_TEXT)) != NULLFILE) {
while (offset = ftell (fp), fgets (buf2, LINELEN - 1, fp)) {
if (!strnicmp (buf2, string, (unsigned) thelen)) {
fseek (fp, offset, SEEK_SET);
break;
}
}
} else
fp = fopentmp (WhitePages, APPEND_TEXT);
fprintf (fp, "%-*s %-14ld\n", thesize, buf, now);
(void) fclose (fp);
kwait (NULL);
}
/* record it in the daily WP Update temp file */
if (bbs)
add_WPUpdate (buf, buf, NULLCHAR, which);
else {
cp = strchr (buf, '@');
if (cp)
*cp++ = 0;
add_WPUpdate (buf, cp, NULLCHAR, which);
}
}
}
}
/* Returns a copy (strdup'ed) of existing entry if string is in whitepages file */
char *
wpageCheck (char *string, int bbs, int updateit, char which)
{
/* note: updateit is NEVER set except sometimes when called from wpageAdd() */
register FILE *fp;
char buf[LINELEN], *retval = NULLCHAR;
register char *cp;
int result, thelen;
int entrysize;
char const *fname;
int skipupdate = 0;
if (!MbWpages || string == NULLCHAR || !*string)
return (retval);
if (!strnicmp (string, "sysop", 5))
return (retval);
entrysize = (bbs) ? WPAGEBBSENTRYSIZE : WPAGEENTRYSIZE;
fname = (bbs) ? WhitePagesBBS : WhitePages;
if ((cp = strchr (string, (bbs) ? '.' : '@')) != NULLCHAR)
thelen = (int) (cp - string);
else
thelen = (int) strlen (string);
result = searchfile (string, fname, buf, entrysize, 0, thelen);
if (result == -1 && !updateit) {
if ((fp = fopennew (fname, READ_TEXT)) != NULLFILE) {
while (fgets (buf, LINELEN - 1, fp)) {
if (!strnicmp (buf, string, (unsigned) thelen)) {
result = 0;
skipupdate = 1;
break;
}
}
(void) fclose (fp);
}
}
if (result != -1) { /* found it */
if (((cp = strpbrk (buf, " \t")) != NULLCHAR))
*cp = '\0';
rip (buf);
retval = strdup (buf);
if (!skipupdate) {
fp = fopen (fname, UPDATE_TEXT);
if (fp != NULLFILE) {
fseek (fp, (long) (long) result * (long) entrysize, 0);
wpageUpdate (fp, string, buf, &buf[(bbs) ? 33 : 14], bbs, updateit, (which != 'G') ? which : 'X');
/* wpageUpdate does the (void) fclose(fp); */
}
}
}
return retval;
}
void
wpageAdd (char *entry, int bbs, int updateit, char which)
{
time_t now;
FILE *fp;
char *last, buf[14];
if (!MbWpages || entry == NULLCHAR)
return;
if (!strnicmp (entry, "sysop", 5))
return;
last = wpageCheck (entry, bbs, updateit, which);
if (!last) {
(void) time (&now);
if (!bbs) {
strncpy (buf, entry, 13);
buf[13] = 0;
if ((last = strchr (buf, '.')) != NULLCHAR)
*last = 0;
entry = buf;
}
if ((fp = fopennew ((bbs) ? WhitePagesBBS : WhitePages, APPEND_TEXT)) != NULLFILE) {
fprintf (fp, "%-*s %-14ld\n", (bbs) ? 32 : 13, entry, now); /* Save h_addr in whitepages file */
kwait (NULL);
(void) fclose (fp);
}
if (bbs)
add_WPUpdate (entry, entry, NULLCHAR, which);
else {
last = strchr (entry, '@');
if (last)
*last++ = 0;
add_WPUpdate (entry, last, NULLCHAR, which);
}
} else
free (last);
}
#endif
#ifdef MAILCMDS
/* Returns 1 if string is in history file or if 2 string appears to be a
* message id generated by our system or 0 if not ours or in history file.
*/
int
msgidcheck (register char *string)
{
register char *cp;
if (string == NULLCHAR)
return 0;
/* BID's that we have generated ourselves are not kept in the history
* file. Such BID's are in the nnnn_hhhh form, where hhhh is a part of
* our hostname, truncated so that the BID is no longer than 11
* characters.
*/
if ((cp = strchr (string, '_')) != NULLCHAR && *(cp + 1) != '\0' &&
strnicmp (cp + 1, Hostname, strlen (cp + 1)) == 0
&& *((Hostname) + strlen (cp + 1)) == '.'
&& (int) strspn (string, "0123456789") == (int) (cp - string))
return 2;
return (bid_check (string));
}
#endif
int
dombfdesc (int argc OPTIONAL, char *argv[], void *p)
{
struct mbx *m;
char *file, *cp, *nm;
FILE *fp;
int k;
#ifdef DOS_GETFILEATTR
unsigned attr;
char name[14];
#endif
m = (struct mbx *) p;
if ((file = permtest (m->path, m->privs, argv[1], RETR_CMD, NULLCHAR, 0)) == NULLCHAR) {
tputs (Noperm);
return 0;
}
#ifdef DOS_GETFILEATTR
(void) _dos_getfileattr (file, &attr);
#endif
nm = strrchr (file, '/');
if (nm == NULLCHAR)
return 0;
*nm++ = 0;
#ifdef DOS_GETFILEATTR
if (attr & FA_DIREC) {
sprintf (name, "%s/", nm);
nm = name;
}
#endif
cp = pathname (file, index_dat);
if ((fp = fopen (cp, APPEND_TEXT)) == NULLFILE) {
tputs ("Can't open description file!\n");
return 0;
}
fprintf (fp, "%-12s", nm);
free (file);
free (cp);
tputs (filedesc);
for (k = 1; k < 38; k++)
tputc (uchar('0' + (k % 10)));
tputc ('\n');
while (mbxrecvline (m) != -1) {
if (!strnicmp (m->line, "/ex", 3)) {
(void) fclose (fp);
return (0);
}
fprintf (fp, " %-37.37s\n", skipwhite (m->line));
}
(void) fclose (fp);
return (-2); /* socket closed here! */
}
#ifdef FILECMDS
int
dodownload (int argc, char *argv[], void *p)
{
struct mbx *m;
FILE *fp;
char *file;
m = (struct mbx *) p;
if (m->stype == 'I')
return (dowhat (argc, argv, p));
if (m->stype == 'E')
return (dozap (argc, argv, p));
if ((file = permtest (m->path, m->privs, argv[1], RETR_CMD, NULLCHAR, 0)) == NULLCHAR) {
tputs (Noperm);
mail_error (downloaddenied, m->name, cmd_line (argc, argv, m->stype));
return 0;
}
#ifdef UNIX
if (!ftpsecuritycheck (file, m->privs, R_OK)) {
tputs (Noperm);
mail_error (downloaddenied, m->name, cmd_line (argc, argv, m->stype));
return 0;
}
#endif
m->state = MBX_DOWNLOAD;
#ifdef TIPMAIL
#ifdef XMODEM
if (m->stype == 'X') {
if (m->type == TIP) { /* xmodem send tip only */
m->state = MBX_XMODEM_TX;
#ifdef MBXTDISC
/* disable the mbox inactivity timeout timer - WG7J */
stop_timer (&m->tdisc);
#endif
(void) doxmodem ('S', file, m);
return 0;
} else {
tputs (xmodemtip);
return 0;
}
}
#endif
#endif
if ((fp = fopen (file, (m->stype == 'U') ? READ_BINARY : READ_TEXT)) == NULLFILE)
tprintf (cannotopen, file, SYS_ERRLIST(errno));
else {
#ifdef MBXTDISC
/* disable the mbox inactivity timeout timer - WG7J */
stop_timer (&m->tdisc);
#endif
if (m->stype == 'U') /* uuencode ? */
(void) uuencode (fp, m->user, file);
else
(void) sendfile (fp, m->user, ASCII_TYPE, 0);
if (fp != NULLFILE)
(void) fclose (fp);
}
free (file);
return 0;
}
#endif
int
dombupload (int argc, char *argv[], void *p)
{
struct mbx *m;
FILE *fp, *uufp = NULLFILE;
char *file;
#ifdef UNIX
int mode = 0x7fff;
#endif
m = (struct mbx *) p;
if (m->stype == 'S') {
m->stype = 'L';
return (dombusers (argc, argv, p));
}
if (m->stype == 'F') {
sprintf (m->line, "%s/%s", FingerDir, m->name);
file = strdup (m->line);
} else if (m->stype == '$') {
sprintf (m->line, "%s/%s.sig", Signature, m->name);
file = strdup (m->line);
#ifdef DELEGATE
} else if (m->stype == 'M') {
sprintf (m->line, "%s/%s.del", Signature, m->name);
file = strdup (m->line);
#endif
} else if ((file = permtest (m->path, m->privs, argv[1], STOR_CMD, NULLCHAR, 0)) == NULLCHAR) {
tputs (Noperm);
mail_error (uploaddenied, m->name, cmd_line (argc, argv, m->stype));
return 0;
}
#ifdef UNIX
if (!ftpsecuritycheck (file, m->privs, W_OK)) {
tputs (Noperm);
mail_error (uploaddenied, m->name, cmd_line (argc, argv, m->stype));
return 0;
}
#endif
#if defined(FILECMDS) && defined(TIPMAIL) && defined(XMODEM)
if (m->stype == 'X') {
if (m->type == TIP) { /* xmodem receive tip only */
m->state = MBX_XMODEM_RX;
#ifdef MBXTDISC
/* disable the mbox inactivity timeout timer - WG7J */
stop_timer (&m->tdisc);
#endif
(void) doxmodem ('R', file, m);
goto secureit;
} else {
tputs (xmodemtip);
return 0;
}
}
#endif
if ((fp = fopen (file, (m->stype == 'U') ? WRITE_BINARY : WRITE_TEXT)) == NULLFILE) {
tprintf (cannotcreate, file, SYS_ERRLIST(errno));
free (file);
return 0;
}
if (m->stype == 'U') {
uufp = fp;
fp = tmpfile ();
}
log (m->user, logupload, file);
m->state = MBX_UPLOAD;
tprintf ("Send %s, %s", (m->stype == 'F') ? "personal information" : (m->stype == 'S') ? "signature information" : (m->stype == 'M') ? "personal message" : "file", Howtoend);
for ( ; ; ) {
if (mbxrecvline (m) == -1) {
unlink (file);
break;
}
if (*m->line == 0x01 || !stricmp (m->line, "/abort")) { /* CTRL-A */
unlink (file);
tputs (MsgAborted);
break;
}
if (*m->line == CTLZ || !strnicmp ("/ex", m->line, 3) || !stricmp (m->line, "."))
break;
fputs (m->line, fp);
#if !defined(UNIX) && !defined(__TURBOC__) && !defined(TNOS_68K)
/* Needed only if the OS uses a CR/LF
* convention and putc doesn't do
* an automatic translation
*/
if (putc ('\r', fp) == EOF)
break;
#endif
if (putc ('\n', fp) == EOF)
break;
}
if (m->stype == 'U') {
#ifdef UNIX
mode =
#else
(void)
#endif
uudecode (fp, uufp);
(void) fclose (uufp);
}
(void) fclose (fp);
#if defined(FILECMDS) && defined(TIPMAIL) && defined(XMODEM)
secureit:
#endif
#ifdef UNIX
if (CREATEsecure) {
(void) chown (file, (uid_t) CREATEuid, (gid_t) CREATEgid);
(void) chmod (file, (mode_t) (mode & CREATEmask));
} else if (m->stype == 'U')
(void) chmod (file, (mode_t) mode);
#endif
free (file);
return 0;
}
void
bbsbump (
char *user,
int zap /* if zap=1, remove entry, else just mark for bumping */
) {
int i;
struct mbx *m = NULLMBX;
/* check the mailbox users */
for (i = 0; i < NUMMBX; i++) {
if ((m = Mbox[i]) != NULLMBX) {
if (!stricmp (m->name, user))
break;
}
}
if (i != NUMMBX && m != NULLMBX) {
if (zap)
exitbbs (m);
else
m->privs |= EXCLUDED_CMD;
}
}
int
dobump (int argc, char *argv[], void *p)
{
struct mbx *m;
m = (struct mbx *) p;
if (!(m->privs & SYSOP_CMD))
tputs (sorry);
else
bbsbump (argv[1], ((argc > 2) && !strnicmp ("now", argv[2], 3)) ? 1 : 0);
return 0;
}
int
dombencode (int argc OPTIONAL, char *argv[] OPTIONAL, void *p)
{
struct mbx *m;
m = (struct mbx *) p;
if (!(m->privs & SYSOP_CMD))
tputs (sorry);
else
(void) doencode (0, (char **) 0, (void *) 0);
return 0;
}
#ifdef FILECMDS
/* uuencode a file -- translated from C++; both versions copyright 1990
by David R. Evans, G4AMJ/NQ0I
*/
static int
uuencode (FILE *infile, int s, char *infilename)
{
int n_read_so_far = 0, n_written_so_far = 0, in_chars, n, mode = 0755;
unsigned long cnt = 0;
unsigned char in[3], out[4], line[100];
#ifdef UNIX
struct stat stb;
if (stat (infilename, &stb) != -1)
mode = stb.st_mode & 0777; /* get real file protection mode */
#endif
usprintf (s, "begin %03o %s\n", mode, infilename);
/* do the encode */
for ( ; ; ) {
in_chars = (int) fread (in, 1, 3, infile);
out[0] = in[0] >> 2;
out[1] = uchar (in[0] << 6);
out[1] = out[1] >> 2;
out[1] = out[1] | (in[1] >> 4);
out[2] = uchar (in[1] << 4);
out[2] = out[2] >> 2;
out[2] = out[2] | (in[2] >> 6);
out[3] = uchar (in[2] << 2);
out[3] = out[3] >> 2;
for (n = 0; n < 4; n++)
out[n] += ' ';
n_read_so_far += in_chars;
for (n = 0; n < 4; n++)
line[n_written_so_far++] = out[n];
if (((in_chars != 3) || (n_written_so_far == 60)) && n_read_so_far > 0) {
line[(n_read_so_far + 2) / 3 * 4] = '\0';
usprintf (s, "%c%s\n", n_read_so_far + ' ', line);
kwait (NULL);
cnt += (unsigned long) n_read_so_far;
n_read_so_far = 0;
n_written_so_far = 0;
}
if (in_chars == 0)
break;
}
if (usprintf (s, " \nend\nsize %lu\n", cnt) == EOF)
return 1;
return 0;
}
int
uudecode (FILE *infile, FILE *outfile)
{
char line[100];
int header = 0;
int n_to_write, n_to_read, n_reads, n, m;
unsigned char b[4], out[3];
int mode = 0x7fff;
rewind (infile);
/* skip till the (begin) line is eaten */
while (!header) {
(void) fgets(line, 100, infile);
if (strstr (line, "begin")) {
header = 1;
sscanf (line, "begin %03o", &mode);
}
}
/* decode the remainder of the file */
while ((void) fgets (line, 100, infile), strncmp (line, "end", 3)) {
n_to_write = (int)line[0] - 32;
n_to_read = ((n_to_write + 2) / 3) * 4;
if (strlen ((char *)line) - 2 < (unsigned int) n_to_read) /* EOF apparently */
n_to_read = 0;
n_reads = n_to_read / 4;
for (n = 0; n < n_reads; n++) {
for (m = 0; m < 4; m++)
b[m] = (unsigned char) line[1 + 4 * n + m] - 32;
/* now do the actual decode */
out[0] = (unsigned char) (b[0] << 2) | ((b[1] & 0x30) >> 4);
out[1] = ((b[1] & 0x0f) << 4) | ((b[2] & 0x3c) >> 2);
out[2] = ((b[2] & 0x03) << 6) | (b[3]);
if (n_to_write > 3)
for (m = 0; m < 3; m++)
fputc(out[m], outfile);
else
for (m = 0; m < n_to_write; m++)
fputc (out[m], outfile);
n_to_write -= m;
}
}
return (mode);
}
#endif
#endif /* MAILBOX */